#include <iostream>
#include <queue>
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <chrono>

struct Task {
    int priority;
    std::chrono::steady_clock::time_point timestamp;
    std::function<void()> func;

    Task(int p, std::chrono::steady_clock::time_point t, std::function<void()> f) :
        priority(p), timestamp(t), func(f) {}

    bool operator<(const Task& t) const {
        if (priority == t.priority)
            return timestamp > t.timestamp;  // 时间戳更晚的优先级更低
        return priority > t.priority;  // 数值更小的优先级更高
    }
};

class ThreadPool {
private:
    std::priority_queue<Task> tasks;
    std::vector<std::thread> workers;
    std::mutex queue_mutex;
    std::condition_variable condition;
    bool stop;

public:
    ThreadPool(size_t threads) : stop(false) {
        for (size_t i = 0; i < threads; ++i) {
            workers.emplace_back([this] {
                while (true) {
                    Task task(0, std::chrono::steady_clock::now(), []{});
                    {
                        std::unique_lock<std::mutex> lock(this->queue_mutex);
                        this->condition.wait(lock, [this] {
                            return this->stop || !this->tasks.empty();
                        });
                        if (this->stop && this->tasks.empty())
                            return;
                        task = this->tasks.top();
                        this->tasks.pop();
                    }
                    task.func();  // execute the task
                }
            });
        }
    }

    template<typename F>
    void enqueue(F&& f, int priority) {
        auto now = std::chrono::steady_clock::now();
        {
            std::unique_lock<std::mutex> lock(queue_mutex);
            tasks.emplace(priority, now, f);
        }
        condition.notify_one();
    }

    ~ThreadPool() {
        stop = true;
        condition.notify_all();
        for (auto& worker : workers) {
            worker.join();
        }
    }
};

// Example usage
int main() {
    ThreadPool pool(4);  // Create a ThreadPool with 4 worker threads
    
    for (int i = 0; i < 16; ++i) {
        int priority = i % 4;  // 0 is highest priority, 3 is lowest
        pool.enqueue([i, priority] {
            std::cout << "Task " << i << " with priority " << priority << " is running." << std::endl;
            std::this_thread::sleep_for(std::chrono::seconds(4 - priority));  // Less sleep for higher priority
            std::cout << "Task " << i << " with priority " << priority << " is done." << std::endl;
        }, priority);
    }

    std::this_thread::sleep_for(std::chrono::seconds(20)); // Wait for all tasks to finish
    std::cout << "All tasks completed." << std::endl;

    return 0;
}